#!/usr/bin/env python
# -*- coding:utf-8 -*- 
# Author: Jeokayne Ataier

'''
解决粘包的关键在于传输数据需要知晓数据大小
控制接收--接收完成之前while True循环
简单版：可以在传输数据时构建，先传输信息大小至对方（设置字节长度），再传输实际数据

利用struck将数据大小打包为4个字节的内容
'''




import socket
import struct
from chardet.universaldetector import UniversalDetector

#获取编码格式(有可能返回空值，必须在下面进行返回值判断：if not dectector.result['encoding']:continue
def GetEncoding(str):
    dectector = UniversalDetector()
    dectector.feed(str)
    dectector.close()
    return dectector.result



#客户端主体代码
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(("127.0.0.1",8881))
#信息收、发循环
while True:
    cmd = input(">>>")
    if not cmd:
        continue

    #打包传输大小信息--4个字节
    client_size = struct.pack("i",len(cmd.encode("utf-8")))
    client.send(client_size)

    #传输数据
    client.send(cmd.encode("utf-8"))


    '''
    客户端传输信息结束，接收服务端传回的信息
    '''

    #接收数据大小信息
    server_size = struct.unpack("i",client.recv(4))[0]
    recv_size = 0
    recv_data = b""
    while recv_size < server_size:
        recv = client.recv(1024)
        recv_data+=recv
        recv_size+=len(recv)
    recv_encodings = GetEncoding(recv_data)

    try:
        '''
        上面已经写好自动获取编码格式的代码，如果自己手动写decode，注意下面的编码：
        1.windows系统返回的byte需要用gbk解码decode
        2.Linux系统返回的byte需要用utf-8解码decode
        '''
        if not recv_encodings['encoding']:
            print(recv_data.decode("utf-8"))
        else:
            print(recv_data.decode(f"{recv_encodings['encoding']}"))
    except UnicodeError as e:
        print("返回值编码错误：",e)
        continue

client.close()